// circle.cpp
// Authors: David Hara and Andrew Forney
// ---------------------------------------------------------------------
// Simple, introductory program to display a circle with a white center
// and edges that transition from red to yellow to green to cyan to blue
// to magenta and then back to red. (radius = 1)
// Some comments and elements shamelessly stolen from Dr. Toal.

#include <math.h>

#ifdef __APPLE_CC__
#include <GLUT/glut.h>
#else
#include <GL/glut.h>
#endif

// Helper function to determine color amounts
void colorer(double d) {
    if(d < 60) {
        glColor3f(1, (d / 60.0), 0);
    } else if(d < 120) {
        glColor3f((120 - d) / 60, 1, 0);
    } else if(d < 180) {
        glColor3f(0, 1, ((d - 120) / 60));
    } else if(d < 240) {
        glColor3f(0, (240 - d) / 60, 1);
    } else if(d < 300) {
        glColor3f((d - 240) / 60, 0, 1);
    } else if(d < 360) {
        glColor3f(1, 0, (360 - d) / 60);
    }
}

// Clears the current window and draws a circle.
void display() {

    // Set every pixel in the frame buffer to the current clear color.
    glClear(GL_COLOR_BUFFER_BIT);

    // Begin drawing triangle strips, starting with the shared center point
    // at the origin. Continue to make strips along the circumference of the
    // circle, changing the color as necessary.
    glBegin(GL_TRIANGLE_FAN);

        // Start with the center vertex
        glColor3f(1, 1, 1); glVertex3f(0.0, 0.0, 0.0);

        // Define constants and a holder for computing radians
        const double DEGREES = 360;
        const double SLICE_SIZE = 0.25;
        const double PI = 3.1415962;
        double radians = 0;

        // Start for loops to add circumference vertices and color them.
        for(double currentAngle = 0; currentAngle <= DEGREES; currentAngle += SLICE_SIZE) {
            colorer(currentAngle);
            radians = currentAngle * (PI / 180.0);
            glVertex3f(cos(radians), sin(radians), 0);
        }

    glEnd();

    // Flush drawing command buffer to make drawing happen as soon as possible.
    glFlush();
}

// Initializes GLUT, the display mode, and main window; registers callbacks;
// enters the main event loop.
int main(int argc, char** argv) {

    // Use a single buffered window in RGB mode (as opposed to a double-buffered
    // window or color-index mode).
    glutInit(&argc, argv);
    glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);

    // Position window at (80,80)-(680,680) and give it a title.
    glutInitWindowPosition(80, 80);
    glutInitWindowSize(600, 600);
    glutCreateWindow("A Simple Circle");

    // Tell GLUT that whenever the main window needs to be repainted that it
    // should call the function display().
    glutDisplayFunc(display);

    // Tell GLUT to start reading and processing events.  This function
    // never returns; the program only exits when the user closes the main
    // window or kills the process.
    glutMainLoop();
}
